import java.util.ArrayList;
import java.util.StringTokenizer;


public class DemoPBFT {

        /**
         * @param args
         */
        
        public static Peer processArguments(String[] args)
        {
            StringTokenizer pidPort = new StringTokenizer(args[Constants.ARG_PID_PORT],":");
            int pid = Integer.parseInt(pidPort.nextToken());
            int port = Integer.parseInt(pidPort.nextToken());
            String peerType = args[Constants.ARG_PEER_TYPE];
            boolean isByzantine = (args[Constants.ARG_BYZ].equals(Constants.BYZ)?true:false);
            
            if(isByzantine)
            {
            	System.out.println("PID: "+pid+" - I AM BYZANTINE! ;-)");
            }
            
            int peerTimeout = Integer.parseInt(args[Constants.ARG_PEER_TIMEOUT]);
            
            ArrayList<Integer> upSet = new ArrayList<Integer>();
            for(int i=Constants.ARG_OTHER_PEERS;i<args.length;i++)
            {
                    StringTokenizer oPidPort = new StringTokenizer(args[i],":");
                    int oPid = Integer.parseInt(oPidPort.nextToken());
                    int oPort = Integer.parseInt(oPidPort.nextToken());
                    upSet.add(oPort);
            }
            Peer bftPeer = new Peer(pid,port,peerType,isByzantine,peerTimeout,upSet);
            return bftPeer;
        }
        
        public static String decideRole(Peer bftPeer)
        {
            // Decide role based on current view
            System.out.println("PID: "+bftPeer.pid+" - My current role is: "+bftPeer.role);
            int primaryPid = bftPeer.view%(bftPeer.totalPeers);
            System.out.println("PID: "+bftPeer.pid+" - The Primary Pid is: "+primaryPid);
            String role = Constants.BACKUP;
            if(bftPeer.role.equals(Constants.BACKUP))
            {
                    if (primaryPid == bftPeer.pid)
                    {
                            role = Constants.PRIMARY;
                    }
            }
            else if(bftPeer.role.equals(Constants.CLIENT))
            {
                    role = Constants.CLIENT;
            }
            bftPeer.primaryPid = primaryPid;
            System.out.println("PID: "+bftPeer.pid+" - My new role is: "+role);
            return role;
        }
        
        public static void main(String[] args) 
        {
            int stateMachineStatus = Constants.CONTINUE_PROCESS;
            Peer bftPeer = processArguments(args);
            while(stateMachineStatus != Constants.EXIT_MACH)
            {
                String role = decideRole(bftPeer);
                if(role.equals(Constants.PRIMARY))
                {
                	if(stateMachineStatus == Constants.VIEW_CHANGE)
                	{
                		stateMachineStatus = bftPeer.playPrimary(true);
                	}
                	else
                	{
                		stateMachineStatus = bftPeer.playPrimary(false);
                	}
                	
                }
                else if(role.equals(Constants.BACKUP))
                {
                        stateMachineStatus = bftPeer.playBackup();
                }
                else if(role.equals(Constants.CLIENT))
                {
                        stateMachineStatus = bftPeer.playClient();
                }
            }
        }
}
